/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 * 
 * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 *
 * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
 * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
 *
 * Contributor(s): 
 *  Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
 *  
 * If you didn't download this code from the following link, you should check
 * if you aren't using an obsolete version: http://www.isqlviewer.com
 */
package org.isqlviewer.swing;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.util.Vector;

import javax.swing.JPanel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * Enhanced version of a container using a variation of the CardLayout.
 * <p>
 * This panel simplifies creating a container that supports a cardLayout in a more intuitive manner.
 * 
 * @author Mark A. Kobold.
 * @see java.awt.CardLayout
 * @version 1.0
 */
public class WizardPanel extends JPanel {

    private static final Insets insets = new Insets(10, 10, 10, 10);
    private static final long serialVersionUID = -4942953182059358257L;
    private transient Vector<ChangeListener> changeListeners;

    /**
     * Default constructor for creating a card panel.
     * <p>
     */
    public WizardPanel() {

        super(true);
        super.setLayout(new Layout());
    }

    /**
     * @param name
     * @return
     */
    public Component getCard(String name) {

        int nChildren = getComponentCount();
        for (int i = 0; i < nChildren; i++) {
            Component child = getComponent(i);
            if (name.equals(child.getName())) {
                return child;
            }
        }
        return null;
    }

    /**
     * @param card
     */
    public void showCard(Component card) {

        if (card.getParent() != this) {
            add(card);
        }
        int index = getVisibleChildIndex();
        if (index != -1) {
            getComponent(index).setVisible(false);
        }
        card.setVisible(true);
        fireStateChanged(new ChangeEvent(this));
        revalidate();
        repaint();
    }

    /**
     * Show the card with the specified name.
     * 
     * @see java.awt.Component#getName
     */
    /**
     * @param name
     */
    public void showCard(String name) {

        int nChildren = getComponentCount();
        for (int i = 0; i < nChildren; i++) {
            Component child = getComponent(i);
            if (child.getName().equals(name)) {
                showCard(child);
                break;
            }
        }
    }

    /**
     * 
     */
    public void showNextCard() {

        if (getComponentCount() <= 0) {
            return;
        }
        try {
            String card = getCurrentCard();
            int index = getVisibleChildIndex();
            if (index >= getComponentCount() - 1) {
                showLastCard();
            } else {
                card = getComponent(++index).getName();
                showCard(card);
            }
        } catch (Throwable t) {
        }
    }

    /**
     * 
     */
    public void showPreviousCard() {

        if (getComponentCount() <= 0) {
            return;
        }
        try {
            String card = getCurrentCard();
            int index = getVisibleChildIndex();
            if (index >= 1) {
                card = getComponent(--index).getName();
                showCard(card);
            } else {
                showFirstCard();
            }
        } catch (Throwable t) {
        }
    }

    /**
     * @return
     */
    public String getCurrentCard() {

        try {
            return getComponent(getVisibleChildIndex()).getName();
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * @param name
     * @return
     */
    public Component removeCard(String name) {

        int nChildren = getComponentCount();
        for (int i = 0; i < nChildren; i++) {
            Component child = getComponent(i);
            if (child.getName().equals(name)) {
                remove(child);
                return child;
            }
        }
        return null;
    }

    /**
     * 
     */
    public void showFirstCard() {

        if (getComponentCount() <= 0) {
            return;
        }
        try {
            String card = getComponent(0).getName();
            showCard(card);
        } catch (Throwable t) {
        }
    }

    /**
     * 
     */
    public void showLastCard() {

        if (getComponentCount() <= 0) {
            return;
        }
        try {
            String card = getComponent(getComponentCount() - 1).getName();
            showCard(card);
        } catch (Throwable t) {
        }
    }

    /**
     * @param l
     */
    public synchronized void removeChangeListener(ChangeListener l) {

        if (changeListeners != null && changeListeners.contains(l)) {
            Vector v = changeListeners;
            v.removeElement(l);
        }
    }

    /**
     * @param l
     */
    public synchronized void addChangeListener(ChangeListener l) {

        Vector<ChangeListener> v = changeListeners == null ? new Vector<ChangeListener>(2) : changeListeners;
        if (!v.contains(l)) {
            v.addElement(l);
            changeListeners = v;
        }
    }

    @Override
    public void setLayout(LayoutManager mgr) {

    }

    protected void fireStateChanged(ChangeEvent e) {

        if (changeListeners != null) {
            Vector listeners = changeListeners;
            int count = listeners.size();
            for (int i = 0; i < count; i++) {
                ((ChangeListener) listeners.elementAt(i)).stateChanged(e);
            }
        }
    }

    protected int getVisibleChildIndex() {

        int nChildren = getComponentCount();
        for (int i = 0; i < nChildren; i++) {
            Component child = getComponent(i);
            if (child.isVisible()) {
                return i;
            }
        }
        return -1;
    }

    public static class Layout implements LayoutManager {

        public void addLayoutComponent(String name, Component child) {

            if (name != null) {
                child.setName(name);
            }
            child.setVisible(child.getParent().getComponentCount() == 1);
        }

        public void removeLayoutComponent(Component child) {

            if (child.isVisible()) {
                Container parent = child.getParent();
                if (parent.getComponentCount() > 0) {
                    parent.getComponent(0).setVisible(true);
                    layoutContainer(parent);
                }
            }
        }

        public Dimension preferredLayoutSize(Container parent) {

            int nChildren = parent.getComponentCount();
            int width = insets.left + insets.right;
            int height = insets.top + insets.bottom;
            for (int i = 0; i < nChildren; i++) {
                Dimension d = parent.getComponent(i).getPreferredSize();
                if (d.width > width) {
                    width = d.width;
                }
                if (d.height > height) {
                    height = d.height;
                }
            }
            return new Dimension(width, height);
        }

        public Dimension minimumLayoutSize(Container parent) {

            int nChildren = parent.getComponentCount();
            int width = insets.left + insets.right;
            int height = insets.top + insets.bottom;
            for (int i = 0; i < nChildren; i++) {
                Dimension d = parent.getComponent(i).getMinimumSize();
                if (d.width > width) {
                    width = d.width;
                }
                if (d.height > height) {
                    height = d.height;
                }
            }
            return new Dimension(width, height);
        }

        public void layoutContainer(Container parent) {

            int nChildren = parent.getComponentCount();
            for (int i = 0; i < nChildren; i++) {
                Component child = parent.getComponent(i);
                if (child.isVisible()) {
                    Rectangle r = parent.getBounds();
                    int width = r.width - (insets.left + insets.right);
                    int height = r.height - (insets.top + insets.bottom);
                    child.setBounds(insets.left, insets.top, width, height);
                    break;
                }
            }
        }
    }

}